package no.sachmuld.methodcombination.examples.adapter.clossimplestyle.foo;

import no.sachmuld.methodcombination.api.MethodInvocation;
import no.sachmuld.methodcombination.api.BehaviourChain;
import no.sachmuld.methodcombination.api.adapter.Simple;
import no.sachmuld.methodcombination.api.adapter.Simple;

import java.util.List;

/**
 *
 */
public abstract class Foo {

    private BehaviourChain<FooBehaviour> chain = new BehaviourChain<>();

    public final List<String> list() {
        return new Simple.List<FooBehaviour, String>(chain) {
            @Override
            protected String executePrimary(FooBehaviour behaviour) {
                return behaviour.list();
            }
        }.execute();
    }

    public final List<String> append() {
        return new Simple.Append<FooBehaviour, String>(chain) {
            @Override
            protected java.util.List<String> executePrimary(FooBehaviour behaviour) {
                return behaviour.append();
            }
        }.execute();
    }

    public final boolean or() {
        return new Simple.Or<FooBehaviour>(chain) {
            @Override
            protected Boolean executePrimary(FooBehaviour behaviour) {
                return behaviour.or();
            }
        }.execute();
    }

    public final boolean and() {
        return new Simple.And<FooBehaviour>(chain) {
            @Override
            protected Boolean executePrimary(FooBehaviour behaviour) {
                return behaviour.and();
            }
        }.execute();
    }

    public final void all() {
        new Simple.All<FooBehaviour>(chain) {
            @Override
            protected Void executePrimary(FooBehaviour behaviour) {
                behaviour.all();
                return null;
            }
        }.execute();
    }

    public final int sum() {
        return new Simple.Sum<FooBehaviour, Integer>(chain, Integer.TYPE) {
            @Override
            protected Integer executePrimary(FooBehaviour behaviour) {
                return behaviour.sum();
            }
        }.execute();
    }

    public final int min() {
        return new Simple.Min<FooBehaviour, Integer>(chain) {
            @Override
            protected Integer executePrimary(FooBehaviour behaviour) {
                return behaviour.min();
            }
        }.execute();
    }

    public final int max() {
        return new Simple.Max<FooBehaviour, Integer>(chain) {
            @Override
            protected Integer executeAround(FooBehaviour behaviour, MethodInvocation<Integer> methodInvocation) {
                return methodInvocation.proceed();
            }

            @Override
            protected Integer executePrimary(FooBehaviour behaviour) {
                return behaviour.max();
            }
        }.execute();
    }

    final protected Foo with(FooBehaviour... behaviours) {
        chain.addAll(behaviours);
        return this;
    }


}
